﻿import kliment.geom.Geom;
import kliment.math.Calc;
import kliment.geom.color.*;

/**
 * ...
 * @author	Kliment
 * @version	1.4.0
 */

class kliment.geom.color.HSVColor extends ColorAbstract {
	private var RADIUS:Number = 100;
	
	public var rawH:Number = 0;
	public var rawS:Number = 0;
	public var rawV:Number = 0;
	
	function HSVColor(host:Color) {
		super(host);
	}
	
	public function get h():Number { return rawH * Geom.FULL_TUTN }
	public function get s():Number { return rawS * RADIUS }
	public function get v():Number { return rawV * RADIUS }
	
	public function setValue(h:Number, s:Number, v:Number, update:Boolean):Void {
		setRawValue(h / Geom.FULL_TUTN, s / RADIUS, v / RADIUS, update);
	}
	
	public function setRawValue(h:Number, s:Number, v:Number, update:Boolean):Void {
		if (update == undefined) update = true;
		if (_roundRawValue(rawH) == _roundRawValue(h) && _roundRawValue(rawS) == _roundRawValue(s) && _roundRawValue(rawV) == _roundRawValue(v))
			return;
		rawH = (h + 1000) % 1;
		rawS = Calc.inInterval(MIN_RAW, MAX_RAW, s);
		rawV = Calc.inInterval(MIN_RAW, MAX_RAW, v);
		if (color && update) 
			color.valueChanged(Color.HSV);
	}
	
	private function _roundRawValue(value:Number):Number {
		return Math.ceil(value * 10000000) / 10000000;
	}
	
	public function toString():String {
		return "[HSVColor h=" + h + " s=" + s + " v=" + v + "]";
	}
	
	public function clone():HSVColor {
		var result:HSVColor = new HSVColor();
		result.setRawValue(rawH, rawS, rawV, false);
		return result;
	}
	
	public function toRGB(rgb:RGBColor):RGBColor { return converToRGB(this, rgb) }
	static public function converToRGB(hsv:HSVColor, rgb:RGBColor):RGBColor {
		if (!rgb) rgb = new RGBColor();
		var rawR:Number;
		var rawG:Number;
		var rawB:Number;
		var rawH:Number = hsv.rawH;
		var rawS:Number = hsv.rawS;
		var rawV:Number = hsv.rawV;
		rawH = (rawH + 1000) % 1;
		var mode:Number = rawH * 6 >> 0;
		var f:Number = rawH * 6 - mode;
		var p:Number = rawV * (1 - rawS);
		var q:Number = rawV * (1 - rawS * f);
		var t:Number = rawV * (1 - rawS * (1 - f));
		switch(mode){
			case 0: rawR = rawV; rawG = t; rawB = p; break;
			case 1: rawR = q; rawG = rawV; rawB = p; break;
			case 2: rawR = p; rawG = rawV; rawB = t; break;
			case 3: rawR = p; rawG = q; rawB = rawV; break;
			case 4: rawR = t; rawG = p; rawB = rawV; break;
			case 5: rawR = rawV; rawG = p; rawB = q; break;
		}
		rgb.setRawValue(rawR, rawG, rawB, false);		
		return rgb;
	}
}